package com.min.main.config.perms;

import cn.hutool.core.collection.CollectionUtil;
import com.min.main.config.ShiroConfig;
import com.min.main.entity.RoleEntity;
import com.min.main.entity.UserEntity;
import com.min.main.service.RoleService;
import com.min.main.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


@Component
public class MinRealm extends AuthorizingRealm {

    @Autowired
    UserService userService;

    @Autowired
    RoleService roleService;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof MinToken;
    }

    /**
     * 认证
     * <p>
     *     每访问一个 {@link ShiroConfig} 中被标记为auth的url时，都会进入此方法认证
     * </p>
     * @param authenticationToken:
     * @return: org.apache.shiro.authc.AuthenticationInfo
     * @author: fengt
     * @date: 2021/4/9 16:58
     **/
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        if (authenticationToken instanceof MinToken) {
            String token = (String) authenticationToken.getPrincipal();
            final UserEntity user = userService.getUserByToken(token);
            if (user == null) {
                throw new ExpiredCredentialsException("无效token");
            }
            user.setToken(token);
            return new SimpleAuthenticationInfo(user, token, this.getName());
        }

        return null;
    }

    /**
     * 授权
     * <p>
     *     每一个被<br/>
     *     {@link org.apache.shiro.authz.annotation.RequiresPermissions }<br/>
     *     {@link org.apache.shiro.authz.annotation.RequiresRoles }<br/>
     *     等注解标记的方法都需要进入此方法对比权限
     * </p>
     * @param principalCollection:
     * @return: org.apache.shiro.authz.AuthorizationInfo
     * @author: fengt
     * @date: 2021/4/9 16:58
     **/
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        if (principalCollection.getPrimaryPrincipal() != null) {
            SimpleAuthorizationInfo info =  new SimpleAuthorizationInfo();
            String token = (String) principalCollection.getPrimaryPrincipal();
            List<RoleEntity> roles = roleService.getByToken(token);
            if (roles == null) {
                throw new ExpiredCredentialsException("无效token");
            }

            if(CollectionUtil.isNotEmpty(roles)) {
                info.setRoles(roles.stream().map(r->r.getCode()).collect(Collectors.toSet()));
                final Set<String> perms = roles.stream().flatMap(r -> r.getPermissions().stream()).collect(Collectors.toSet());
                if (CollectionUtil.isNotEmpty(perms)) {
                    info.setStringPermissions(perms);
                }
            }

            return info;
        } else {
            return null;
        }
    }

}
